// Copyright Gary Evans 2006-2007.

using System;
using System.Collections.Generic;
using System.Text;

using Taumuon.Jabuka.Physics;
using Collision = Taumuon.Jabuka.Physics.Collision;

namespace Taumuon.Jabuka.MainApp
{
    /// <summary>
    /// Collisions between three objects simultaneously, and shock propagation (as in Newton's cradle).
    /// </summary>
    [Scene("3. Many object collision, shock propagation", "Shows collisions between many objects simultaneously, and a collision that should be propagated along a row of touching objects.")]
    public class Scene3 : BaseScene
    {
        #region Overrides

        /// <summary>
        /// Resets the Scene to its starting point.
        /// </summary>
        public override void ResetScene()
        {
            List<Collision.Sphere> spheres = new List<Collision.Sphere>();
            drawableObjects = new List<IDrawable>();

            double locationY = -80.0;
            double locationX = 0.0;
            AddMultipleCollisionSpheres(locationX, locationY, Density.Low, Density.Low, Density.Low, spheres, drawableObjects);

            locationY = -45.0;
            locationX = 30.0;
            AddMultipleCollisionSpheres(locationX, locationY, Density.Medium, Density.Low, Density.Low, spheres, drawableObjects);

            locationY = -10.0;
            locationX = 0.0;
            AddMultipleCollisionSpheres(locationX, locationY, Density.Low, Density.Medium, Density.Low, spheres, drawableObjects);

            locationY = 25.0;
            locationX = 30.0;
            AddMultipleCollisionSpheres(locationX, locationY, Density.Low, Density.Medium, Density.High, spheres, drawableObjects);

            #region Add a line of spheres a la Newton's Cradle.

            locationY = 55;
            const double radius = 7.0;
            const Density density = Density.Medium;
            const double startingLocationXStationary = 0.0;
            const double startingLocationXMoving = -50.0;
            const int numberOfStationarySpheres = 4;
            const int numberOfMovingSpheres = 2;

            // The moving spheres that will collide with the line of stationary spheres.
            for (int i = 0; i < numberOfMovingSpheres; ++i)
            {
                AddSphere(density,
                    new Vector(startingLocationXMoving + (i * 2.0 * radius), locationY, 0.0),
                    new Vector(2.0, 0.0, 0.0),
                    radius, spheres, drawableObjects);
            }

            for (int i = 0; i < numberOfStationarySpheres; ++i)
            {
                AddSphere(density,
                    new Vector(startingLocationXStationary + (i * 2.0 * radius), locationY, 0.0),
                    new Vector(), radius, spheres, drawableObjects);
            }

            #endregion Add a line of spheres a la Newton's Cradle.

            this.collisionManager = new Collision.CollisionManager(spheres);
        }

        #endregion Overrides

        #region Helper Methods

        private void AddMultipleCollisionSpheres(double locationX, double locationY, Density densityMoving, Density densityStationaryTop, 
            Density densityStationaryBottom, List<Collision.Sphere> spheres, List<IDrawable> drawableObjects)
        {
            const double stationarySpheresSeparation = 0.1;
            const double radius = 7.0;
            const double initialXLocationMoving = -20.0;
            const double initialXLocationStationary = 20.0;

            const double movingVelocityX = 2.0;
            AddSphere(densityMoving,
                new Vector(locationX + initialXLocationMoving, locationY, 0.0),
                new Vector(movingVelocityX, 0.0, 0.0),
                radius, spheres, drawableObjects);

            AddSphere(densityStationaryTop,
                new Vector(locationX + initialXLocationStationary, locationY + ( radius + ( stationarySpheresSeparation ) / 2.0 ), 0.0 ),
                new Vector(), radius, spheres, drawableObjects);

            AddSphere(densityStationaryBottom,
                new Vector(locationX + initialXLocationStationary, locationY - ( radius + ( stationarySpheresSeparation ) / 2.0 ), 0.0 ),
                new Vector(), radius, spheres, drawableObjects);
        }

        #endregion Helper Methods
    }
}
